<template>
  <div class="login-container">
    <vue-particles
      v-if="enableDynamicBg"
      :color="dynamicBgColor"
      :particleOpacity="0.1"
      :particlesNumber="15"
      shapeType="circle"
      :particleSize="100"
      :linesColor="dynamicBgColor"
      :linesWidth="1"
      :lineLinked="true"
      :lineOpacity="0.4"
      :linesDistance="150"
      :moveSpeed="3"
      :hoverEffect="true"
      hoverMode="grab"
      :clickEffect="true"
      clickMode="push"
    ></vue-particles>

    <div class="login-inner-container">
      <div class="release-info" @click="showSelectUser = !showSelectUser">
        <span>{{ releaseCycle }}</span>
      </div>

      <transition name="fade-transform-top">
        <el-form
          v-show="!showSelectUser"
          ref="loginForm"
          :model="formData"
          :rules="formRules"
          class="login-form"
          :class="{ mobile: device === 'mobile' }"
          autocomplete="on"
          label-position="left"
        >
          <div class="title-container">
            <h3 class="title">
              <svg-icon
                v-if="title === 'Noctua Admin'"
                icon-class="noctua"
                className="logo-icon"
              /><br v-if="device !== 'mobile'" />
              {{ title }}
            </h3>
          </div>

          <el-form-item prop="account">
            <span class="svg-container">
              <svg-icon icon-class="user" />
            </span>
            <el-input
              ref="account"
              v-model="formData.account"
              placeholder="account"
              name="account"
              type="text"
              tabindex="1"
              autocomplete="on"
            />
          </el-form-item>

          <el-tooltip
            v-model="capsTooltip"
            content="Caps lock is On"
            placement="right"
            manual
          >
            <el-form-item prop="password">
              <span class="svg-container">
                <svg-icon icon-class="password" />
              </span>
              <el-input
                :key="passwordType"
                ref="password"
                v-model="formData.password"
                :type="passwordType"
                placeholder="Password"
                name="password"
                tabindex="2"
                autocomplete="on"
                @keyup="checkCapslock"
                @blur="capsTooltip = false"
                @keyup.enter="handleLogin"
              />
              <span class="show-pwd" @click="showPassword">
                <svg-icon
                  :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'"
                />
              </span>
            </el-form-item>
          </el-tooltip>

          <el-button
            :loading="loading"
            type="primary"
            size="large"
            style="width:100%"
            @click.prevent="handleLogin"
            >登 录</el-button
          >
        </el-form>
      </transition>

      <transition name="fade-transform-bottom">
        <div
          v-if="showSelectUser"
          class="login-form"
          :class="{ mobile: device === 'mobile' }"
        >
          <select-user :userList="userList" @handle-confirm="handleSetUser" />
        </div>
      </transition>

      <div class="svg-link-container">
        <div class="icon-container">
          <a href="https://v3.cn.vuejs.org/" title="Vue.js" target="_blank"
            ><svg-icon icon-class="vue" className="vue-icon"
          /></a>
        </div>
        <div class="icon-container">
          <a
            href="https://element-plus.gitee.io/#/zh-CN"
            title="Element Plus"
            target="_blank"
          >
            <svg-icon icon-class="element" className="element-icon" />
          </a>
        </div>
        <div class="icon-container">
          <a
            href="https://vant-contrib.gitee.io/vant/v3/#/zh-CN"
            title="Vant"
            target="_blank"
          >
            <svg-icon icon-class="vant" className="vant-icon" />
          </a>
          <a
            href="https://vant-contrib.gitee.io/vant/v3/#/zh-CN"
            title="Vant"
            target="_blank"
          >
            <span class="vant-text">Vant</span>
          </a>
        </div>
        <div class="icon-container">
          <a
            href="http://git.seaskysh.com.cn:8800/dongjunhua/vue-element-next"
            title="GitLab"
            target="_blank"
          >
            <svg-icon icon-class="gitlab" className="gitlab-icon" />
          </a>
        </div>
      </div>

      <div class="info-container">
        <div class="text-container">
          <span style="margin-right:10px"
            >Ver. {{ `${version}(${coreVersion})` }}
          </span>
          <span>Powered by Vue.js v3 Framework</span>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import {
  ref,
  onMounted,
  reactive,
  nextTick,
  toRefs,
  computed,
  watch
} from 'vue';
import { useStore } from 'vuex';
import { useRoute } from 'vue-router';
import AuthenticationToken from '@/core/model/AuthenticationToken';
import SelectUser from './components/SelectUser';
import ResizeMixin from '@/layout/mixin/ResizeHandler';
export default {
  name: 'Login',
  components: {
    SelectUser
  },
  mixins: [ResizeMixin],
  setup() {
    // important!! this can't be used inside setup
    // useStore & useRouter can only be used inside setup
    const store = useStore();
    const route = useRoute();
    const loginForm = ref(null);
    const account = ref(null);
    const password = ref(null);
    const data = reactive({
      title: store.state.app.applicationName,
      releaseCycle: store.state.app.releaseCycle,
      version: store.state.app.version,
      coreVersion: store.state.app.coreVersion,
      enableDynamicBg: store.state.app.enableDynamicBg,
      formData: {
        account: 'admin',
        password: '123456'
      },
      formRules: {
        account: [
          { required: true, trigger: 'blur', validator: validateAccount }
        ],
        password: [
          { required: true, trigger: 'blur', validator: validatePassword }
        ]
      },
      passwordType: 'password',
      capsTooltip: false,
      loading: false,
      showDialog: false,
      redirect: undefined,
      otherQuery: {},
      userList: [],
      showSelectUser: false
    });

    const dynamicBgColor = computed(() => {
      if (store.state.app.themes.find(t => t.active).name === 'light') {
        return '#aaa';
      }
      if (store.state.app.themes.find(t => t.active).name === 'dark') {
        return '#ddd';
      }
      return '#ddd';
    });

    const validateAccount = (rule, value, callback) => {
      // do valid here
      // if invalid, callback(new Error())
      callback();
    };
    const validatePassword = (rule, value, callback) => {
      // do valid here
      // if invalid, callback(new Error())
      callback();
    };
    const checkCapslock = e => {
      const { key } = e;
      data.capsTooltip = key && key.length === 1 && key >= 'A' && key <= 'Z';
    };
    const showPassword = async () => {
      if (data.passwordType === 'password') {
        data.passwordType = '';
      } else {
        data.passwordType = 'password';
      }
      await nextTick();
      password.value.focus();
    };
    const handleLogin = () => {
      loginForm.value.validate(async valid => {
        if (valid) {
          const token = new AuthenticationToken(
            data.formData.account,
            data.formData.password
          );
          await store.dispatch('subject/login', token);
          const userList = store.state.subject.account.users;
          if (userList) {
            if (userList.length > 1) {
              data.userList = userList;
              data.showSelectUser = true;
            } else if (userList.length === 1) {
              handleSetUser(userList[0].id);
            }
          }
        } else {
          // console.log('error submit!!');
          return false;
        }
      });
    };
    const handleSetUser = async userId => {
      const permitOptions = { authorizationToken: userId };
      if (data.otherQuery.redirect_uri) {
        permitOptions.afterPermitted = token => {
          window.location.href = `${data.otherQuery.redirect_uri}?code=${token}`;
        };
      }
      await store.dispatch('subject/permit', permitOptions);
    };
    const getQuery = query => {
      return Object.keys(query).reduce((acc, cur) => {
        if (cur !== 'redirect') {
          acc[cur] = query[cur];
        }
        return acc;
      }, {});
    };
    const focus = () => {
      if (data.formData.account === '') {
        account.value.focus();
      } else if (data.formData.password === '') {
        password.value.focus();
      }
    };

    watch(
      () => route.path,
      () => {
        data.otherQuery = getQuery(route.query);
      },
      { immediate: true }
    );

    onMounted(() => {
      focus();
    });

    const device = computed(() => store.state.app.device);
    const sidebar = computed(() => store.state.app.sidebar);

    return {
      loginForm,
      account,
      password,
      ...toRefs(data),
      dynamicBgColor,
      checkCapslock,
      showPassword,
      handleLogin,
      handleSetUser,
      device,
      sidebar
    };
  }
};
</script>

<style lang="scss" scoped>
/* particles */
#particles-js {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

/* footer */
.svg-link-container,
.info-container {
  position: absolute;
  display: flex;
  width: 100%;
  height: 40px;
  justify-content: center;
}

.svg-link-container {
  bottom: 15%;

  .icon-container {
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 10px;

    .vue-icon {
      width: 1.3em !important;
      height: 1.3em !important;
    }
    .element-icon {
      width: 5em !important;
      height: 2em !important;
    }
    .vant-icon {
      width: 1.3em !important;
      height: 1.3em !important;
    }
    .vant-text {
      position: relative;
      top: -1px;
      margin-left: 5px;
      color: #888;
      font-size: 14px;
      font-family: 'Open Sans', -apple-system, BlinkMacSystemFont,
        'Helvetica Neue', Helvetica, Segoe UI, Arial, Roboto, 'PingFang SC',
        'miui', 'Hiragino Sans GB', 'Microsoft Yahei', sans-serif;
      user-select: none;
    }
    .gitlab-icon {
      width: 4.8em !important;
      height: 2em !important;
    }
  }
}

.info-container {
  bottom: calc(15% - 50px);

  .text-container {
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 10px;

    span {
      color: #aaaaaa;
      font-size: 14px;
    }
  }
}
</style>

<style lang="scss">
/* 修复input 背景不协调 和光标变色 */
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */

$bg: #283443;
$light_gray: #fff;
$cursor: #fff;

@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
  .login-container .el-input input {
    color: $cursor;
  }
}

/* reset element-ui css */
.login-container {
  .el-input {
    display: inline-block;
    height: 47px;
    width: 85%;

    .el-input__wrapper {
      background: transparent;
      border: 0px;
      -webkit-appearance: none;
      border-radius: 0px;
      padding: 12px 5px 12px 15px;
      // color: $light_gray;
      height: 47px;
      // caret-color: $cursor;
      font-size: 16px;
      border: 0px;
      box-shadow: 0 0 0 0 !important;
      width: 100%;

      &:-webkit-autofill,
      &:hover,
      &.is-focus {
        -webkit-text-fill-color: var(--color-subMenuActiveText) !important;
        -webkit-box-shadow: 0 0 0px 1000px transparent inset !important;
        background-color: transparent;
        background-image: none;
        background: transparent !important;
        border: 0px;
        box-shadow: 0 0 0 0 !important;
      }
      input {
        caret-color: var(--color-subMenuActiveText) !important;
        color: var(--color-subMenuActiveText) !important;
        &:-webkit-autofill {
          -webkit-text-fill-color: var(--color-subMenuActiveText) !important;
          -webkit-box-shadow: 0 0 0px 1000px transparent inset !important;
        }
        &:-internal-autofill-selected {
          -webkit-text-fill-color: var(--color-subMenuActiveText) !important;
          -webkit-box-shadow: 0 0 0px 1000px transparent inset !important;
          transition: background-color 5000s ease-in-out 0s; /*通过延时渲染背景色变相去除背景颜色*/
          background-color: transparent !important;
          background-image: none;
        }
      }
    }
  }

  .el-form-item {
    border: 1px solid rgba(255, 255, 255, 0.1);
    background: rgba(0, 0, 0, 0.1);
    border-radius: 5px;
    color: #454545;
  }
}
</style>

<style lang="scss" scoped>
$bg: rgb(41, 39, 50);
$dark_gray: #889aa4;
$light_gray: #eee;

.login-container {
  min-height: 100%;
  width: 100%;
  overflow: hidden;
  position: relative;
  display: flex;
  justify-content: center;

  .login-inner-container {
    min-height: 600px;
    width: 100%;
    overflow: hidden;
    position: relative;
    display: flex;
    justify-content: center;

    .release-info {
      width: 100px;
      height: 100px;
      display: flex;
      justify-content: center;
      align-items: center;
      background-image: linear-gradient(#409eff, #3dc7d5);
      // background-color: #409eff;
      position: fixed;
      top: -50px;
      right: -50px;
      transform: rotate(45deg);
      cursor: pointer;

      span {
        user-select: none;
        padding-top: 65px;
        font-size: 18px;
        font-weight: bold;
        color: #eeeeee;
      }
    }
  }

  .login-form {
    position: absolute;
    width: 400px;
    max-width: 100%;
    overflow: hidden;
    margin: 15vh auto 0;
    padding: 20px 20px 40px 20px;
    &.mobile {
      padding: 0px 20px;
      .title-container {
        .title {
          .logo-icon {
            font-size: 75px;
            position: relative;
            top: 15px;
            left: -5px;
          }
        }
      }
    }
  }

  .tips {
    font-size: 14px;
    // color: #fff;
    margin-bottom: 10px;

    span {
      &:first-of-type {
        margin-right: 16px;
      }
    }
  }

  .svg-container {
    padding: 6px 5px 6px 15px;
    color: $dark_gray;
    vertical-align: middle;
    width: 30px;
    display: inline-block;
  }

  .title-container {
    position: relative;

    .title {
      font-size: 26px;
      margin: 0px auto 40px auto;
      text-align: center;
      font-weight: bold;

      .logo-icon {
        font-size: 120px;
      }
    }
  }

  .show-pwd {
    position: absolute;
    right: 10px;
    top: 7px;
    font-size: 16px;
    color: $dark_gray;
    cursor: pointer;
    user-select: none;
  }

  .thirdparty-button {
    position: absolute;
    right: 0;
    bottom: 6px;
  }

  @media only screen and (max-width: 470px) {
    .thirdparty-button {
      display: none;
    }
  }
}
</style>
